package pl.edu.agh.jemo.evolution.objfunc;

import pl.edu.agh.jemo.evolution.population.Population;
import pl.edu.agh.jemo.evolution.specimen.Specimen;

/**
 * Abstract class for  special objective functions used to calculate density of population in given specimen neighbourhood.
 * Calculations are made based on specimen genotype, and genotype of other specimen in population.
 * Although specimen holds population reference itself, interface provides methods for manual population reference setting.
 * It is designed that way, in order to allow developer extending that class to move some calculations common for every specimen to setPopulationReferenceMethod.
 * 
 * @author Marcin Zbijowski
 */
public abstract class CrowdingObjectiveFunction implements ObjectiveFunction {
	
	/**
	 * Population reference used to calculate specimen value
	 */
	protected Population population;
	
	/**
	 * Method called when population reference changes.
	 * It is supposed to be overriden by subclass when needed.
	 */
	protected abstract void populationChanged();
	
	/**
	 * Changes population reference and recalculates inner parameters related with it.
	 * Method calls populationChanged after changing population reference value.
	 * This method should also be called after any genotype change of specimen inside population, even if population reference itself remains unchanged.
	 * 
	 * @param population New population reference
	 */
	final public void setPopulationReference(Population population) {
		this.population = population;
		populationChanged();
	}
	
	/**
	 * Performs evaluation of given specimen from implemented criteria point of view.
	 * Calculations should be based on specimen Genotype and parameters stored in specific
	 * ObjectiveFunction instance.
	 * Specimen reference should not change while calculations.
	 * 
	 * @param specimen Specimen reference for which value is calculated.
	 * @return Calculated Double value derived from specimen genotype.
	 */
	public abstract Double calculateValue(Specimen specimen);
}
